Minting policy
Now we can continue with a simple minting policy example.
The final result can be found at HarmonicLabs/simple-minting-pluts
.
Project set up
We will start from the simple-minting-pluts
example:
git clone https://github.com/HarmonicLabs/simple-minting-pluts.git
cd simple-minting-pluts
git remote remove origin
This gives us a simple project structure:
./simple-minting-pluts
├── contracts
│ └── minting.ts
├── next.config.js
├── next-env.d.ts
├── package.json
├── package-lock.json
├── src
│ ├── components
│ │ └── ConnectionHandler.tsx
│ ├── offchain
│ │ ├── getTxBuilder.ts
│ │ ├── mesh-utils.ts
│ │ └── mintNft.ts
│ ├── pages
│ │ ├── _app.tsx
│ │ ├── _document.tsx
│ │ └── index.tsx
│ └── styles
│ ├── globals.css
│ └── Home.module.css
└── tsconfig.json
Install dependencies
Just like the Hello plu-ts example; this project already comes with plu-ts as dependecy; all we need to do to then is to run
npm install
Project overview
From the project structure we see that the code can be found in the src
folder and the contracts
folder.
The contracts
only file is the minting.ts
one; which always success and exports the compiled result.
import { Address, PScriptContext, ScriptType, Credential, Script, compile, pfn, unit, passert } from "@harmoniclabs/plu-ts";
const contract = pfn([
PScriptContext.type
], unit)
(({ redeemer, tx, purpose }) => {
return passert.$(true);
});
export const compiledContract = compile(contract);
export const script = new Script(
ScriptType.PlutusV3,
compiledContract
);
export const scriptTestnetAddr = new Address(
"testnet",
Credential.script(script.hash)
);
The other file is the offchain/mintNft.ts
, which includes the logic for building and executing the transaction for the NFT minting.
import { BrowserWallet } from "@meshsdk/core";
import { Value, Address } from "@harmoniclabs/plu-ts";
import { BlockfrostPluts } from "@harmoniclabs/blockfrost-pluts";
import { scriptTestnetAddr, script } from "../../contracts/minting";
import { toPlutsUtxo } from "./mesh-utils";
import getTxBuilder from "./getTxBuilder";
export async function mintNft(wallet: BrowserWallet, projectId: string): Promise<string> {
const recipient = Address.fromString(
await wallet.getChangeAddress()
);
const Blockfrost = new BlockfrostPluts({ projectId });
const txBuilder = await getTxBuilder(Blockfrost);
const myUTxOs = (await wallet.getUtxos()).map(toPlutsUtxo);
if (myUTxOs.length === 0) {
throw new Error("have you requested founds from the faucet?");
}
const utxo = myUTxOs.find(u => u.resolved.value.lovelaces > 15_000_000);
if (utxo === undefined) {
throw new Error("not enough ada");
}
const unsignedTx = await txBuilder.buildSync({
inputs: [{ utxo }],
changeAddress: recipient,
collaterals: [utxo],
// We need to declare a collateral return in order
// to store the minted token in the user wallet
collateralReturn: {
address: utxo.resolved.address,
value: Value.sub(utxo.resolved.value, Value.lovelaces(5_000_000))
},
// We need to declare the minting policy for the token
mints: [{
// This is the name and amount of tokens we want to mint
value: Value.singleAsset(
scriptTestnetAddr.paymentCreds.hash,
Buffer.from('Test Token'),
1
),
// We pass the script as inline and the redeemer address
script: {
inline: script,
policyId: scriptTestnetAddr.paymentCreds.hash,
redeemer: recipient.toData()
}
}]
});
const txStr = await wallet.signTx(unsignedTx.toCbor().toString());
return await Blockfrost.submitTx(txStr);
}
Test it out
To test it out run
npm run dev
And navigate to the specified url (eg. http://localhost:3000/
);
Then connect your wallet.
And click on the Mint NFT
button.
If everything works correctly you should be prompted to sign a transaction.